#include "Request.h"

#include "../Util/common.h"
#include <chrono>

#include <iostream>
    
Request::Request(std::function<bool()> send, int overtime, int retry, int serial) : send_(send), nOvertime_(overtime), nReTry_(retry), bresponse_(false) , u16Sserial_(serial)
{
    std::cout << CurrentTimeString() << "serial: " << u16Sserial_ << " retry:" << nReTry_ << " overtime:" << nOvertime_ << std::endl;
}

int Request::WaitResponse()
{
    int n = 1;
    while (true)
    {
        unsigned long long ullWaitSeconds = factorial(n) * nOvertime_;
        while (!bresponse_)
        {
            std::cout << CurrentTimeString() << "\n";
            std::unique_lock<std::mutex> ul(mutex_cv_response_);

            std::cout << CurrentTimeString() << " wait_for_seconds:" << ullWaitSeconds<< std::endl;
            cv_response_.wait_for(ul, std::chrono::seconds(ullWaitSeconds));
            if (!bresponse_)
            {
                std::cout << CurrentTimeString() << " timeout\n";
                if (n < nReTry_+1)
                {
                    std::cout << CurrentTimeString() << " retry: " << n << ",overtime:" << ullWaitSeconds *(n+1)<< std::endl;
                    Send();
                    break;
                }
                else
                {
                    goto finished;
                }
            }
            else
            {
                std::cout << CurrentTimeString() << " Get Response: "<< std::boolalpha <<  bresponse_<<"\n";
                return 0;
            }
            
        }
        
        ++n;
    }
finished:    
    std::cout << CurrentTimeString() << " Get Response Nothing: Return\n";
    return -1;
}

int Request::Send()
{
    std::cout << CurrentTimeString() << " Send()\n";
    if (false == send_())
    {
        return -1;
    }
    
    return 0;
}

int Request::GetResponse()
{   
    {
        std::unique_lock<std::mutex> ul(mutex_cv_response_);
        bresponse_ = true;
    }
    cv_response_.notify_one();
    return 0;
}

int Request::DoRequest()
{
    int ret = 0;
    ret = Send();
    if (0!= ret)
    {
        return ret;
    }
    
    return WaitResponse();
}